﻿using System;
using System.Net;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Windows.Threading;
using Skyper.Shared;
using System.Collections.Generic;
using System.Threading;

namespace Skyper.Phone.Model {
	public sealed class SkypeSync {
		#region Fields
		private String hostname;
		private readonly Random rand = new Random();

		private Timer timerSyncContacts;
		#endregion
		#region Constructor
		public SkypeSync() {
			
		}
		#endregion
		#region Private
		private String GetUrl() {
			return hostname + "/" + rand.Next(1, 999).ToString() + "/";
		}
		private Byte[] ReadStream(Stream stream) {
			using (var mem = new MemoryStream()) {
				Byte[] data = new Byte[4096];

				int r = 0;

				while ((r = stream.Read(data, 0, data.Length)) != 0) {
					mem.Write(data, 0,r);
					
				}
				return mem.ToArray();
			}
		}
		private String ReadString(Stream stream) {
			var data = ReadStream(stream);
			return Encoding.UTF8.GetString(data, 0, data.Length);
		}
		private bool IsArgsOk(AsyncCompletedEventArgs args) {
			if (args.Cancelled) {
				return false;
			}
			if (args.Error != null) {
				return false;
			}
			return true;
		}


		private void LoginResult(IAsyncResult result) {
			try {
				HttpWebRequest web = result.AsyncState as HttpWebRequest;
				var resp = web.EndGetResponse(result) as HttpWebResponse;

				var stream = resp.GetResponseStream();

				String data = ReadString(stream);
				if (data == "OK") {
					this.Status = SkypeStatus.Online;
					//this.Dispatcher.BeginInvoke(this.SyncContacts);

					this.StartSync();
				} else {
					this.Status = SkypeStatus.Offline;
				}
				
			} catch {

			}
			if (this.HasDispatcher) {
				this.Dispatcher.BeginInvoke(OnStatusChanged);
			} else {
				this.OnStatusChanged();
			}
		}
		private void GetContactsResponse(IAsyncResult result) {
			try {
				HttpWebRequest web = result.AsyncState as HttpWebRequest;
				var resp = web.EndGetResponse(result) as HttpWebResponse;

				var stream = resp.GetResponseStream();

				List<ContactModel> list = new List<ContactModel>();

				if (ContactModel.Resume(stream, list)) {
					ContactModel[] arr = list.ToArray();
					if (this.HasDispatcher) {
						
						this.Dispatcher.BeginInvoke(new Action<ContactModel[]>((ContactModel[] data) => {
							Globals.Cache.Contacts = data;
						}), new Object[]{arr});
					} else {
						Globals.Cache.Contacts = arr;
					}
					//
				}
			} catch {

			}
		}


		private void OnStatusChanged() {
			if (this.StatusChanged == null) {
				return;
			}
			this.StatusChanged(this, EventArgs.Empty);
		}

		private HttpWebRequest CreateRequest() {
			var web = HttpWebRequest.CreateHttp(this.GetUrl());
			web.AllowReadStreamBuffering = true;
			web.UserAgent = "TEST";
			return web;
		}

		private void StartSync() {
			if (this.Syncing) {
				return;
			}

			this.timerSyncContacts = new Timer(SyncContacts, null, TimeSpan.Zero, TimeSpan.FromSeconds(60));

			this.Syncing = true;
		}
		private void StopSync() {
			if (!this.Syncing) {
				return;
			}

			this.timerSyncContacts.Dispose();
			
		}

		private void SyncContacts(Object state) {
			var web = this.CreateRequest();
			web.Headers["ACTION"] = "GETCONTACTS";
			Thread.Sleep(1000);
			web.BeginGetResponse(GetContactsResponse, web);
		}
		#endregion
		#region Public
		public void Connect(String hostname) {
			this.hostname = hostname;
		}
		public void Login(String password) {
			var web = this.CreateRequest();
			web.Headers["ACTION"] = "LOGIN";
			web.BeginGetResponse(LoginResult,web);
			//this.client.Headers["ACTION"] = "LOGIN";
			//this.client.DownloadStringAsync(GetUrl(),new Action<String>(LoginResponse));
		}
		#endregion
		#region Property
		public Boolean Syncing {
			get;
			private set;
		}
		public SkypeStatus Status {
			get;
			set;
		}
		public Dispatcher Dispatcher {
			get;
			set;
		}
		Boolean HasDispatcher {
			get { return this.Dispatcher != null; }
		}
		#endregion
		#region Events
		public event EventHandler StatusChanged;
		#endregion
	}
}
